﻿// Fill out your copyright notice in the Description page of Project Settings.


#include "AbilitySystem/AbilityTaskes/TargetDataUnderMouse.h"

#include "AbilitySystemComponent.h"

UTargetDataUnderMouse* UTargetDataUnderMouse::CreateTargetDataUnderMouse(UGameplayAbility* OwningAbility)
{
	UTargetDataUnderMouse* MyObj = NewAbilityTask<UTargetDataUnderMouse>(OwningAbility);
	return MyObj;
}

void UTargetDataUnderMouse::Activate()
{
	//加查是否是本地控制
	const bool bIsLocallyControlled = Ability->GetCurrentActorInfo()->IsLocallyControlled();
	if(bIsLocallyControlled)
	{
		sendMouseCursorData();
	}else
	{
		//服务器上能力激活的情况
		const FGameplayAbilitySpecHandle SpecHandle = GetAbilitySpecHandle();
		const FPredictionKey ActivationPredictionKey = GetActivationPredictionKey();
		//通过能力系统组件设置一个委托，档收到目标数据后，回调方法进行有效数据的广播，ValidData.Broadcast(DataHandle);
		AbilitySystemComponent.Get()->AbilityTargetDataSetDelegate(SpecHandle,ActivationPredictionKey).AddUObject(this,&UTargetDataUnderMouse::OnTargetDataReplicatedCallback);
		//如果委托没有设置成功，就需要等待玩家的数据传输
		const bool bCalledDelegate = AbilitySystemComponent.Get()->CallReplicatedTargetDataDelegatesIfSet(SpecHandle, ActivationPredictionKey);
		if (!bCalledDelegate)
		{
			//需要等待数据传输
			SetWaitingOnRemotePlayerData();
		}
	}
}

void UTargetDataUnderMouse::sendMouseCursorData()
{
	//创建当前情景的预测密钥，函数内的所有内容都将被预测
	FScopedPredictionWindow ScopedPrediction(AbilitySystemComponent.Get());
	
	//获取光标的命中结果
	//获取玩家控制器
	APlayerController* PC =Ability->GetCurrentActorInfo()->PlayerController.Get();
	//调用玩家光标下获取的目标
	FHitResult CursorHit;
	PC->GetHitResultUnderCursor(ECC_Visibility,false,CursorHit);
	//目标数据的控制句柄
	FGameplayAbilityTargetDataHandle DataHandle;
	//创建一个新的目标数据FGameplayAbilityTargetData_SingleTargetHit类型
	FGameplayAbilityTargetData_SingleTargetHit* Data = new FGameplayAbilityTargetData_SingleTargetHit();
	//将命中结果设置给目标数据
	Data->HitResult = CursorHit;
	//句柄中打包目标数据
	DataHandle.Add(Data);
	//通过能力系统组件上传目标数据到服务器
	AbilitySystemComponent->ServerSetReplicatedTargetData(
		GetAbilitySpecHandle(),
		GetActivationPredictionKey(),
		DataHandle,
		FGameplayTag(),
		AbilitySystemComponent->ScopedPredictionKey);
	//判断是否应该广播数据
	if (ShouldBroadcastAbilityTaskDelegates())
	{
		ValidData.Broadcast(DataHandle);
	}
}

void UTargetDataUnderMouse::OnTargetDataReplicatedCallback(const FGameplayAbilityTargetDataHandle& DataHandle,
	FGameplayTag ActivationTag)
{
	//能力系统组件消耗客户端复制数据，已经收到数据，不需要缓存了
	AbilitySystemComponent->ConsumeClientReplicatedTargetData(GetAbilitySpecHandle(), GetActivationPredictionKey());
	//判断是否应该广播数据
	if (ShouldBroadcastAbilityTaskDelegates())
	{
		ValidData.Broadcast(DataHandle);
	}
}
